<!DOCTYPE html>
<html lang="zh-CN">
	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>微信群语音聊天</title>
		<link rel="stylesheet" href="./css/toast.css" />
		<link rel="stylesheet" href="./css/chartVoice.css" />
		<style>
			/* 新增群聊样式 */
			.group-members {
				display: flex;
				flex-wrap: wrap;
				justify-content: center;
				margin: 20px 0;
				gap: 15px;
			}
			
			.member-item {
				display: flex;
				flex-direction: column;
				align-items: center;
				width: 80px;
			}
			
			.member-avatar {
				width: 60px;
				height: 60px;
				border-radius: 50%;
				object-fit: cover;
				border: 2px solid #ddd;
				position: relative;
			}
			
			.member-avatar.speaking {
				border-color: #09bb07;
				box-shadow: 0 0 10px rgba(9, 187, 7, 0.5);
			}
			
			.member-name {
				margin-top: 5px;
				font-size: 12px;
				color: #fff;
				text-align: center;
				width: 100%;
				overflow: hidden;
				text-overflow: ellipsis;
				white-space: nowrap;
			}
			
			.member-status {
				font-size: 10px;
				color: #aaa;
			}
			
			.speaker-view {
				position: relative;
				width: 100%;
				height: 200px;
				margin-bottom: 20px;
			}
			
			.main-speaker {
				width: 120px;
				height: 120px;
				border-radius: 50%;
				object-fit: cover;
				border: 3px solid #09bb07;
				position: absolute;
				left: 50%;
				transform: translateX(-50%);
				box-shadow: 0 0 15px rgba(9, 187, 7, 0.7);
			}
			
			/* 调整控制按钮布局 */
			.control-buttons {
				display: flex;
				justify-content: space-around;
				width: 100%;
				padding: 0 20px;
				position: fixed;
				bottom: 30px;
			}
			
			.control-button {
				display: flex;
				flex-direction: column;
				align-items: center;
				background: rgba(255, 255, 255, 0.1);
				border: none;
				border-radius: 50%;
				width: 60px;
				height: 60px;
				color: white;
				font-size: 12px;
				/* margin: 0 5px; */
			}
			
			.control-button i {
				font-size: 24px;
				margin-bottom: 5px;
			}
			
			.control-button.end-call {
				background: #f44336;
			}
			
			.control-button.active {
				background: rgba(9, 187, 7, 0.3);
			}
			
			.call-info {
				text-align: center;
				margin-bottom: 20px;
			}
			
			.call-title {
				font-size: 18px;
				color: #fff;
				margin-bottom: 5px;
			}
			
			.call-status {
				font-size: 14px;
				color: #aaa;
			}
		</style>
	</head>
	<body>
		<!-- 群聊通话中界面 -->
		<div class="voice-container" id="groupVoiceCall">
			<div class="call-info">
				<div class="call-title">微信群语音聊天</div>
				<div class="call-status">00:05:23</div>
			</div>
			
			<!-- 主说话人视图 -->
			<div class="speaker-view">
				<img id="mainSpeakerAvatar" src="https://via.placeholder.com/120/333/666" alt="主说话人" class="main-speaker">
			</div>
			
			<!-- 成员列表 -->
			<div class="group-members" id="groupMembers">
				<!-- 成员将通过JS动态添加 -->
			</div>
			
			<!-- 控制按钮 -->
			<div class="control-buttons">
				<button class="control-button mute" id="muteBtn">
					<img class="fa" src="./images/microphone.svg" alt="" />
					<span>静音</span>
				</button>
				<button class="control-button speaker" id="speakerBtn">
					<img class="fa" src="./images/volume-up.svg" alt="" />
					<span>扬声器</span>
				</button>
				<button class="control-button invite" id="inviteBtn">
					<img class="fa" src="./images/user-plus.svg" alt="" />
					<span>邀请</span>
				</button>
				<button class="control-button end-call" id="endCallBtn">
					<img class="fa" src="./images/phone-slash.svg" alt="" />
					<span>挂断</span>
				</button>
			</div>
		</div>
		
		<!-- 来电界面 -->
		<div id="incomingGroupCall">
			<div class="incoming-call">
				<div class="caller-info">
					<img src="https://via.placeholder.com/150/333/666" alt="头像" class="caller-avatar">
					<div class="caller-name">微信群聊</div>
					<div class="call-status">群语音通话邀请...</div>
					<div class="call-members">
						<span>成员: 张三, 李四, 王五</span>
					</div>
				</div>
				
				<div class="answer-buttons">
					<div class="decline-call" id="declineCallBtn">
						<img class="fa" src="./images/phone-slash.svg" alt="" />
					</div>
					<div class="accept-call" id="acceptCallBtn">
						<img class="fa" src="./images/phone.svg" alt="" />
					</div>
				</div>
			</div>
		</div>
		
		<!-- toast提示 -->
		<div id="toast" class="toast hide">
			<div class="toast-content">
				<p id="toastMessage"></p>
			</div>
		</div>
		
		<script type="text/javascript" src="./js/uni.webview.1.5.2.js"></script>
		<script src="./js/AgoraRTC_N-4.8.0.js"></script>
		<script>
			// 在初始化代码前加入
			window.addEventListener('unhandledrejection', (event) => {
			  if (event.reason?.message?.includes("Failed to execute 'getStats'")) {
			    event.preventDefault(); // 阻止控制台报错
			    console.warn("[AgorRTC 内部错误已忽略]", event.reason);
			  }
			});
			// 方案1：等待 UniApp 环境就绪事件
			document.addEventListener('UniAppJSBridgeReady', () => {
				console.log('UniAppJSBridgeReady:'); // 处理接收到的消息
			});
			
			// 发送给外层信息
			function sendToUniApp(message) {
				console.log("向外层发送消息:"+message);
				// 方法1：标准 UniApp 方式
				if (window.uni?.postMessage) {
					uni.postMessage({
						data: message
					});
					return;
				}
				
				// 方法2：URL Scheme 回退
				try {
					location.href = `uniwebview://postMessage?data=${encodeURIComponent(JSON.stringify(message))}`;
				} catch (e) {
					console.error('URL Scheme 失败:', e);
				}
				
				// 方法3：通过 parent 通信（如果是 iframe 嵌套）
				if (window.parent !== window) {
					window.parent.postMessage({
						type: 'webview',
						data: message
					}, '*');
				}
			}
			
			// 工具函数：解析 URL 参数
			function getUrlParams() {
				const urlParams = new URLSearchParams(window.location.search);
				const paramsObject = {};
				urlParams.forEach((value, key) => {
					paramsObject[key] = value;
				});
				return paramsObject;
			}
			
			const params = getUrlParams();
			console.log("params 参数:", params);
			
			let isSelf = params.isSelf;
			if (isSelf == true) {
				document.getElementById('acceptCallBtn').style.display = 'none';
			} else {
				document.getElementById('acceptCallBtn').style.display = 'flex';
			}
			
			// 获取DOM元素
			const incomingCall = document.getElementById('incomingGroupCall');
			const groupVoiceCall = document.getElementById('groupVoiceCall');
			const acceptCallBtn = document.getElementById('acceptCallBtn');
			const declineCallBtn = document.getElementById('declineCallBtn');
			const endCallBtn = document.getElementById('endCallBtn');
			const muteBtn = document.getElementById('muteBtn');
			const speakerBtn = document.getElementById('speakerBtn');
			const inviteBtn = document.getElementById('inviteBtn');
			const groupMembers = document.getElementById('groupMembers');
			const mainSpeakerAvatar = document.getElementById('mainSpeakerAvatar');
			
			const channelInfo = JSON.parse(decodeURIComponent(params.channelInfo));
			const userInfo = JSON.parse(params.userInfo);
			const groupInfo = JSON.parse(params.groupInfo || '{}'); // 新增群组信息
			
			console.log('channelInfo', channelInfo);
			console.log('userInfo', userInfo);
			console.log('groupInfo', groupInfo);
			
			// 设置群聊名称
			if (groupInfo.groupName) {
				Array.from(document.getElementsByClassName('caller-name')).forEach(function(item) {
					item.innerText = groupInfo.groupName;
				});
				document.querySelector('.call-title').innerText = groupInfo.groupName;
			}
			
			// 设置群成员信息
			if (groupInfo.members) {
				const membersText = groupInfo.members.map(m => m.name).join(', ');
				document.querySelector('.call-members span').innerText = `成员: ${membersText}`;
			}
			
			const userId = userInfo.id;
			let currentMainSpeaker = null; // 当前主说话人ID
			
			// 模拟来电铃声
			function playRingtone() {
				console.log("播放来电铃声...");
			}
			
			// 接听电话
			acceptCallBtn.addEventListener('click', async function() {
				await joinChannel();
			});
			
			// 拒接电话
			declineCallBtn.addEventListener('click', function() {
				incomingCall.style.display = 'none';
				console.log("已拒绝群语音通话");
				const call_request = {
					callerId: "caller",
					status: false,
					timestamp: Date.now(),
					userId: userId,
					type: 'group_voice'
				};
				sendToUniApp(call_request);
			});
			
			// 挂断电话
			endCallBtn.addEventListener('click', function() {
				handeUp(userId);
			});
			
			// 静音按钮
			muteBtn.addEventListener('click', async function() {
				this.classList.toggle('active');
				if (this.classList.contains('active')) {
					// this.querySelector('i').className = 'fas fa-microphone-slash';
					this.querySelector('img').src='./images/microphone-slash.svg'
					if (localAudioTrack) {
						localAudioTrack.setVolume(0);
					}
					console.log("已静音");
				} else {
					// this.querySelector('i').className = 'fas fa-microphone';
					this.querySelector('img').src='./images/microphone.svg'
					if (localAudioTrack) {
						localAudioTrack.setVolume(100);
					}
					console.log("取消静音");
				}
			});
			
			// 扬声器按钮
			speakerBtn.addEventListener('click', async function() {
				this.classList.toggle('active');
				if (this.classList.contains('active')) {
					// this.querySelector('i').className = 'fas fa-volume-up';
					this.querySelector('img').src='./images/volume-up.svg'
					console.log("扬声器已开启");
					// 这里可以设置远程音频的音量
					updateRemoteAudioVolume(100);
				} else {
					// this.querySelector('i').className = 'fas fa-volume-off';
					this.querySelector('img').src='./images/volume-off.svg'
					console.log("扬声器已关闭");
					updateRemoteAudioVolume(50);
				}
			});
			
			// 邀请按钮
			inviteBtn.addEventListener('click', function() {
				console.log("邀请更多人加入");
				const invite_request = {
					callerId: "invite",
					timestamp: Date.now(),
					userId: userId,
					type: 'group_voice'
				};
				sendToUniApp(invite_request);
			});
			
			// 用户挂断
			function handeUp(userUid) {
				groupVoiceCall.style.display = 'none';
				console.log("群语音通话已结束");
				const call_request = {
					callerId: "handelUp",
					status: false,
					timestamp: Date.now(),
					userId: userUid,
					type: 'group_voice'
				};
				sendToUniApp(call_request);
				stopCallTimer();
				leaveChannel();
			}
			
			// 开始通话计时器
			let callTimer = null;
			
			function startCallTimer() {
				let seconds = 0;
				const timerElement = document.querySelector('.call-status');
				
				callTimer = setInterval(function() {
					seconds++;
					const hours = Math.floor(seconds / 3600);
					const minutes = Math.floor((seconds % 3600) / 60);
					const secs = seconds % 60;
					
					timerElement.textContent =
						`${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
				}, 1000);
			}
			
			// 停止通话计时
			function stopCallTimer() {
				if (callTimer) {
					clearInterval(callTimer);
					callTimer = null;
				}
			}
			
			// AgoraRTC 客户端和轨道管理
			let client = null;
			let localAudioTrack = null;
			let remoteUsers = {}; // 存储远程用户信息
			
			// 加入频道
			async function joinChannel() {
				const appId = channelInfo.appId.trim() || null;
				const channel = channelInfo.channel.trim() || null;
				const token = channelInfo.token.trim() || null;
				const userId = userInfo.id.trim() || null;
				
				if (!appId || !channel) {
					console.log("App ID 和频道名不能为空");
					return;
				}
				
				try {
					showToast('正在连接...');
					const devices = await AgoraRTC.getMicrophones();
					if (devices.length === 0) {
						console.log('未找到麦克风设备');
						handleJoinError(userId, '未找到麦克风设备');
						return;
					}
					
					console.log("正在初始化客户端...");
					AgoraRTC.setLogLevel(2); // 设置日志级别
					
					// 创建纯音频客户端
					client = AgoraRTC.createClient({
						mode: "rtc",
						codec: "vp8"
					});
					
					console.log("初始化成功", client);
					
					// 加入频道
					console.log("正在加入频道");
					const uid = await client.join(appId, channel, token || null, userId);
					console.log('本地用户ID', uid);
					
					// 用户加入事件
					client.on("user-joined", async (user) => {
						console.log(`用户 ${user.uid} 加入了频道`);
						console.log('remoteUsers',client.remoteUsers)
						if (client.remoteUsers.length >= 1) {
							// 自动发布音频流
							await publishAudio();
							
							// 显示群聊界面
							incomingCall.style.display = 'none';
							groupVoiceCall.style.display = 'block';
						}
						// 不需要立即处理，等待用户发布流
					});
					
					// 监听用户发布流事件
					client.on("user-published", async (user, mediaType) => {
						if (mediaType === "audio") {
							await client.subscribe(user, mediaType);
							console.log(`远程用户 ${user.uid} 发布了音频流`);
							
							// 存储远程用户信息
							remoteUsers[user.uid] = {
								user: user,
								audioTrack: user.audioTrack,
								isSpeaking: false,
								speakingLevel: 0
							};
							
							// 播放远程音频
							user.audioTrack.play();
							
							// 更新UI
							updateGroupMembersUI();
							
							// 如果是第一个加入的用户，开始计时
							if (Object.keys(remoteUsers).length === 1) {
								startCallTimer();
							}
						}
					});
					
					// 监听用户取消发布流事件
					client.on("user-unpublished", (user, mediaType) => {
						if (mediaType === "audio") {
							console.log(`远程用户 ${user.uid} 取消了音频流`);
							delete remoteUsers[user.uid];
							updateGroupMembersUI();
							
							// 如果主说话人离开，重置主说话人
							if (currentMainSpeaker === user.uid) {
								currentMainSpeaker = null;
								updateMainSpeaker();
							}
							if(remoteUsers.length>0){
								showToast(`${user.uid} 已离开`)
							}else{
								handeUp('')
							}
						}
					});
					
					// 监听用户离开事件
					client.on("user-left", (user) => {
						console.log(`远程用户 ${user.uid} 已离开`);
						delete remoteUsers[user.uid];
						updateGroupMembersUI();
						
						// 如果主说话人离开，重置主说话人
						if (currentMainSpeaker === user.uid) {
							currentMainSpeaker = null;
							updateMainSpeaker();
						}
						if(remoteUsers.length>0){
							showToast(`${user.uid} 已离开`)
						}else{
							handeUp('')
						}
					});
					
					// 启用音频等级检测
					client.enableAudioVolumeIndicator();
					client.on("volume-indicator", (volumes) => {
						volumes.forEach((volume) => {
							if (volume.uid === userId) {
								// 本地用户音量
								updateLocalSpeakingStatus(volume.level > 5);
							} else {
								// 远程用户音量
								if (remoteUsers[volume.uid]) {
									remoteUsers[volume.uid].speakingLevel = volume.level;
									remoteUsers[volume.uid].isSpeaking = volume.level > 5;
									
									// 更新主说话人
									if (volume.level > 5 && (!currentMainSpeaker || volume.level > (remoteUsers[currentMainSpeaker]?.speakingLevel || 0))) {
										currentMainSpeaker = volume.uid;
										updateMainSpeaker();
									}
								}
							}
						});
						
						// 更新所有用户的说话状态
						updateSpeakingStatusUI();
					});
					
					// 网络质量检测
					client.on("network-quality", (stats) => {
						// console.log('network-quality',stats)
						// 确保 stats 存在再使用
						if (stats) updateNetworkStatus(stats);
					});
					
				} catch (error) {
					console.log(`加入频道失败: ${error.message}`);
					console.error(error);
					handleJoinError(userId, '获取麦克风权限失败');
					stopCallTimer();
				}
			}
			
			// 发布本地音频流
			async function publishAudio() {
				if (!client) {
					console.log("请先加入频道");
					return;
				}
				
				try {
					console.log("正在获取麦克风权限...");
					
					// 创建本地音频轨道
					localAudioTrack = await AgoraRTC.createMicrophoneAudioTrack({
						encoderConfig: "speech_standard", // 语音优化配置
						AEC: true, // 回声消除
						ANS: true // 降噪
					});
					
					// 监听本地音频音量变化
					localAudioTrack.setVolume(100);
					localAudioTrack.on("volume-change", (volume) => {
						updateLocalSpeakingStatus(volume > 50);
					});
					
					localAudioTrack.on("track-ended", () => {
						console.error("音频轨道意外结束！");
					});
					
					// 发布本地音频轨道
					console.log("正在发布本地音频流...");
					await client.publish([localAudioTrack]);
					console.log("本地音频流已发布,本地用户" + userId);
					
				} catch (error) {
					console.log(`发布音频流失败: ${error.message}`);
					
					// 发生错误时关闭轨道
					if (localAudioTrack) {
						localAudioTrack.close();
						localAudioTrack = null;
					}
					
					handlePublishError(userId, '获取麦克风权限失败');
					stopCallTimer();
				}
			}
			
			// 取消发布本地音频流
			async function unpublishAudio() {
				if (!client) {
					console.log("客户端未初始化");
					return;
				}
				
				try {
					console.log("正在取消发布本地音频流...");
					
					if (localAudioTrack) {
						await client.unpublish([localAudioTrack]);
						localAudioTrack.close();
						localAudioTrack = null;
					}
					
					console.log("已取消发布本地音频流");
					
				} catch (error) {
					console.log(`取消发布失败: ${error.message}`);
					console.error(error);
				}
			}
			
			// 离开频道
			async function leaveChannel() {
				if (!client) {
					console.log("客户端未初始化");
					return;
				}
				
				try {
					console.log("开始挂断流程...");
					
					// 1. 先取消发布所有轨道
					if (localAudioTrack) {
						console.log("取消发布音频轨道...");
						await client.unpublish([localAudioTrack]);
						localAudioTrack.close();
						localAudioTrack = null;
					}
					
					// 2. 然后离开频道
					console.log("离开频道...");
					await client.leave();
					client = null;
					
					console.log("挂断流程完成");
					
				} catch (error) {
					console.error("挂断过程中出错:", error);
					// 即使出错也尝试强制清理
					forceCleanup();
					throw error;
				}
			}
			
			// 强制清理资源
			function forceCleanup() {
				if (localAudioTrack) {
					try {
						localAudioTrack.close();
					} catch (e) {
						console.warn("强制关闭音频轨道时出错:", e);
					}
					localAudioTrack = null;
				}
				
				if (client) {
					try {
						client.leave();
					} catch (e) {
						console.warn("强制离开频道时出错:", e);
					}
					client = null;
				}
				
				remoteUsers = {};
			}
			
			// 更新远程音频音量
			function updateRemoteAudioVolume(volume) {
				Object.values(remoteUsers).forEach(user => {
					if (user.audioTrack) {
						user.audioTrack.setVolume(volume);
					}
				});
			}
			
			// 更新群成员UI
			function updateGroupMembersUI() {
				// 清空现有成员
				groupMembers.innerHTML = '';
				
				// 添加本地用户
				const localMember = document.createElement('div');
				localMember.className = 'member-item';
				localMember.innerHTML = `
					<img src="${userInfo.avatar || 'https://via.placeholder.com/60/555/888'}" 
						 class="member-avatar ${localSpeaking ? 'speaking' : ''}" 
						 alt="我的头像">
					<div class="member-name">我</div>
					<div class="member-status">${muteBtn.classList.contains('active') ? '已静音' : '在线'}</div>
				`;
				groupMembers.appendChild(localMember);
				
				// 添加远程用户
				Object.values(remoteUsers).forEach(user => {
					const member = document.createElement('div');
					member.className = 'member-item';
					member.innerHTML = `
						<img src="${getUserAvatar(user.user.uid)}" 
							 class="member-avatar ${user.isSpeaking ? 'speaking' : ''}" 
							 alt="成员头像">
						<div class="member-name">${getUserName(user.user.uid)}</div>
						<div class="member-status">${user.isSpeaking ? '正在说话' : '在线'}</div>
					`;
					groupMembers.appendChild(member);
				});
			}
			
			// 更新主说话人
			function updateMainSpeaker() {
				if (currentMainSpeaker) {
					const speaker = remoteUsers[currentMainSpeaker];
					if (speaker) {
						mainSpeakerAvatar.src = getUserAvatar(currentMainSpeaker);
						mainSpeakerAvatar.style.display = 'block';
						return;
					}
				}
				
				// 没有主说话人或主说话人离开，显示默认
				mainSpeakerAvatar.src = 'https://via.placeholder.com/120/333/666';
				mainSpeakerAvatar.style.display = 'block';
			}
			
			// 更新说话状态UI
			function updateSpeakingStatusUI() {
				const members = document.querySelectorAll('.member-avatar');
				members.forEach(member => {
					member.classList.remove('speaking');
				});
				
				// 更新远程用户说话状态
				Object.values(remoteUsers).forEach(user => {
					if (user.isSpeaking) {
						const memberAvatar = document.querySelector(`.member-avatar[alt="成员头像"][src="${getUserAvatar(user.user.uid)}"]`);
						if (memberAvatar) {
							memberAvatar.classList.add('speaking');
						}
					}
				});
				
				// 更新本地用户说话状态
				if (localSpeaking) {
					const localAvatar = document.querySelector('.member-avatar[alt="我的头像"]');
					if (localAvatar) {
						localAvatar.classList.add('speaking');
					}
				}
			}
			
			let localSpeaking = false;
			
			// 更新本地用户说话状态
			function updateLocalSpeakingStatus(isSpeaking) {
				localSpeaking = isSpeaking;
				updateSpeakingStatusUI();
			}
			
			// 根据用户ID获取用户名
			function getUserName(uid) {
				// 这里可以根据实际业务逻辑从群组信息中获取用户名
				if (uid === userId) return '我';
				if (groupInfo.members) {
					const member = groupInfo.members.find(m => m.id === uid);
					if (member) return member.name;
				}
				return `用户${uid}`;
			}
			
			// 根据用户ID获取头像
			function getUserAvatar(uid) {
				// 这里可以根据实际业务逻辑从群组信息中获取头像
				if (uid === userId) return userInfo.avatar || 'https://via.placeholder.com/60/555/888';
				if (groupInfo.members) {
					const member = groupInfo.members.find(m => m.id === uid);
					if (member) return member.avatar;
				}
				return 'https://via.placeholder.com/60/333/666';
			}
			
			function handleJoinError(userId, error) {
				const call_request = {
					callerId: "groupAudioCall",
					status: false,
					timestamp: Date.now(),
					userId: userId,
					error: error
				};
				sendToUniApp(call_request);
			}
			
			function handlePublishError(userId, error) {
				const call_request = {
					callerId: "groupAudioCall",
					status: false,
					timestamp: Date.now(),
					userId: userId,
					error: error
				};
				sendToUniApp(call_request);
			}
			
			// 更新网络状态显示
			function updateNetworkStatus(stats) {
				let status = "网络良好";
				let color = "#34c759";
				
				// 下行网络质量
				if (stats.downlinkNetworkQuality > 4) {
					status = "网络较差";
					color = "#ff9500";
					showToast('网络较差');
				}
				if (stats.downlinkNetworkQuality > 6) {
					status = "网络非常差";
					color = "#ff3b30";
					showToast('网络非常差');
				}
			}
			
			// 提示框
			function showToast(message) {
				const toast = document.getElementById('toast');
				const toastMessage = document.getElementById('toastMessage');
				toastMessage.textContent = message;
				toast.classList.add('show');
				toast.classList.remove('hide');
				setTimeout(() => {
					toast.classList.remove('show');
					setTimeout(() => {
						toast.classList.add('hide');
					}, 300);
				}, 2000);
			}
			
			// 页面加载时播放铃声
			window.addEventListener('load', function() {
				playRingtone();
			});
		</script>
	</body>
</html>